/** @format */
import { forEach as foreach, keyBy } from 'lodash'
// _.each

/**
 * @function isIterable 判断是否为可迭代对象
 * @param obj
 * @returns true | false
 */
function isIterable(obj: any): boolean {
    // || obj[Symbol.isConcatSpreadable] === true
    return obj != null && typeof obj[Symbol.iterator] === 'function'
}

/**
 * @function isObject 判断是否为对象
 * @param obj
 * @returns true | false
 */
function isObject(obj: any): boolean {
    // lodash 将 function 也视作 object 类型，故作区分
    return typeof obj === 'object' && obj !== null
}

/**
 * @function isMap 判断是否为 Map
 * @param obj
 * @returns true | false
 */
function isMap(obj: any): boolean {
    // return _.isMap(obj)
    return obj instanceof Map
}
/**
 * @function forEach 遍历普通对象或可迭代对象（以下简称可遍历对象）：
 * 1. 统一对象遍历方法：String、Array、Map、Set、Object 等可遍历对象均可传入
 * 2. 可自定义返回值做为遍历结果，默认为 []
 * 3. 设置 isReceive 为 true 后接收每次遍历回调函数的返回值并 push 进新数组中，最终返回该数组
 * 4. 当 callbackfn 返回 '\break' 作为信号时，循环将提前中断，并直接返回 results
 * 0. 目前只返回数组，后续实现：通过一次循环处理原始数据，返回可遍历对象（或对象集），省去 .map、.filter 等的链式调用。
 * @param callbackfn 回调函数，接收三个参数：当前元素、当前索引、待遍历对象
 * @param toBeTraversed 待遍历对象，必须为可遍历对象
 * @param isReceive 是否接收回调函数的返回值，默认为 false
 * @returns results 返回值为遍历结果列表，
 */
// _.forEach
export function forEach<Item>(
    toBeTraversed: Traversable<Identifier, Item>,
    callbackfn: (item: Item, id: Identifier, collection: Traversable<Identifier, Item>) => any,
    isReceive: boolean = false,
    thisArg: any = toBeTraversed
    // returnType: any[] = [] 返回值类型，默认为 null
): any[] {
    // 初始化返回值
    const results: any[] = []
    // 辅助函数
    // const nextID = () => {}
    // const handelCallback = (item,id,traversable) => {
    // }
    // 判断 toBeTraversed 参数类型：object: {iterable: {array}}
    if (Array.isArray(toBeTraversed)) {
        // 遍历数组
        const arr = toBeTraversed as Array<Item>
        const length = arr.length
        for (let index = 0; index < length; index++) {
            const value = arr[index]
            const result = callbackfn.call(thisArg, value, index, arr)
            if (result === '\break') break
            isReceive && results.push(result)
        }
    } else if (isIterable(toBeTraversed)) {
        // 遍历可迭代对象
        const iterable = toBeTraversed as Iterable<Item>
        // Symbol(item)
        let id = 0
        for (const item of iterable) {
            const result = callbackfn.call(thisArg, item, id, iterable)
            if (result === '\break') break
            isReceive && results.push(result)
        }
    } else if (isObject(toBeTraversed)) {
        // 遍历普通对象 or 字典
        const obj = toBeTraversed as Dict<string, Item>
        for (const key in obj) {
            const value = obj[key]
            const result = callbackfn.call(thisArg, value, key, obj)
            if (result === '\break') break
            isReceive && results.push(result)
        }
    } else throw new Error('检查 toBeTraversed 参数类型：必须为可遍历对象。')
    return results
}
export function listToDict(list: {}[], key: string) {
    const dict = keyBy(list, key)
    return dict
}

/*
debugger
// 测试数据
const goods_list = [
	{
		gid: "g001",
		gname: "商品名称1",
		img: "",
		price: 128,
		count: 1,
		tags: ["折扣"],
		isSelected: true,
		isValid: true,
		recommends: ["g101"],
	},
	{
		gid: "g002",
		gname: "商品名称2",
		img: "",
		price: 24,
		count: 3,
		tags: ["热销"],
		isSelected: false,
		isValid: true,
		recommends: ["g101"],
	},
	{
		gid: "g003",
		gname: "商品名称3",
		img: "",
		price: 18,
		count: 5,
		tags: ["新品"],
		isSelected: true,
		isValid: true,
		recommends: ["g101"],
	},
	{
		gid: "g000",
		gname: "商品名称0",
		img: "",
		price: 9.9,
		count: 5,
		tags: ["热销"],
		isSelected: false,
		isValid: false,
		recommends: ["g101"],
	},
]

debugger
console.log(
	forEach(goods_list, (item, index, collection) => {
		console.log(item)
		// return item
	})
)
// console.log(listToDict(goods_list, "gid"))
*/
